using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Xml.Linq;
using Crap4Net.CCParsers;

namespace Crap4Net.CoverageParsers
{
    public class NCover3CoverageParser : BaseCoverageParser
    {
        protected override void ParseDataFromXml(string reportFileName)
        {
            var xDoc = XDocument.Load(reportFileName);
            var methods = GetAllMethods(xDoc);
            foreach (var method in methods)
            {
                var parser = new NCoverMethodParser();
                var methodSignature = parser.ParseMethodSignature(method);
                int coverage = GetCoverageValue(method);

                Data.Add(new CoverageDataEntry(methodSignature, coverage));
            }

        }

        private IEnumerable<XElement> GetAllMethods(XDocument xDoc)
        {
            return xDoc.Descendants("method");
        }

        private int GetCoverageValue(XElement method)
        {

            var total = TotalVisits(method);
            var actualVisits = ActualVisits(method);

            if (total != 0)
                return actualVisits * 100 / total;
            else
                return 0;
        }

        private int TotalVisits(XElement method)
        {
            var allVisits = from visit in method.Elements("seqpnt")
                            where (int)visit.Attribute("l") != 0    // theres a dummy visit on line 0 which ncover buffers in???
                            select visit;
            var grouped = allVisits.GroupBy(p => (int)p.Attribute("l"));
            var distinctVisits = grouped.Select(g => g.First());
            return distinctVisits.Count();
        }

        private int ActualVisits(XElement method)
        {
            var allActualVisits = from visit in method.Elements("seqpnt")
                                  where (((int)visit.Attribute("vc") > 0) && ((int)visit.Attribute("l") != 0)) // theres a dummy visit on line 0 which ncover buffers in???
                          select visit;
            var grouped = allActualVisits.GroupBy(p => (int)p.Attribute("l")); 
            var distinctVisits = grouped.Select(g => g.First());
            return distinctVisits.Count(); 
        }
    }

}
